package mbp.message;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

/**
 * Implementuje konwersje obiektow informacyjnych do elementow w formacie xml i dowrotnie. 
 * @author wojtek
 *
 */
public class TagBuilder 
{
	private Logger logger = Logger.getLogger(this.getClass());
	public TagBuilder()
	{
		
	}
	
	public Element getResourceTag(Document doc, resource rc, String tagName)
	{
		Element resourceElement = doc.createElement(tagName);
		resourceElement.setAttribute("type", rc.type);
		
		if(rc.resourceid != null)
		{
			Element resourceId = doc.createElement("resourceid");
			resourceId.setTextContent(rc.resourceid);
			resourceElement.appendChild(resourceId);
		}
	
		if(rc.owner != null)
		{
			Element owner = doc.createElement("owner");
			owner.setTextContent(rc.owner);
			resourceElement.appendChild(owner);
		}
	
		if(rc.vdate != null)
		{
			Element vdate = doc.createElement("vdate");
			vdate.setTextContent(rc.vdate);
			resourceElement.appendChild(vdate);
		}
	
		if(rc.features.size()>0)
		{
			Element features = doc.createElement("features");
			resourceElement.appendChild(features);
			for(int j=0; j<rc.features.size(); j++)
			{
				Element feature = doc.createElement("feature");
				feature.setAttribute("value", rc.features.get(j).getValue());
				feature.setTextContent(rc.features.get(j).getName());
				features.appendChild(feature);
				
			}
		}
		
		//logger.debug("Created new resource xml Element from resource info: " + rc.type);
		return resourceElement;
	}
	
	public Element getResourceValidationTag(Document doc, validation rcv, String tagName)
	{
		Element validation = doc.createElement(tagName);
		validation.setTextContent(rcv.type);
		validation.setAttribute("value", rcv.condition);
		validation.setAttribute("intvalue", rcv.intvalue);
		
		//logger.debug("Created new validation xml Element from validation info: " + rcv.type);
		return validation;
	}
	
	public Element getResourceUtilityTag(Document doc, utility rcu, String tagName)
	{
		//utworzenie tagu <utility\>
		Element utilityElement = doc.createElement(tagName);
		//utility.setTextContent(utilities.get(i).type);
		utilityElement.setAttribute("type", rcu.type);
		
		Element functionElement = doc.createElement("function");
		functionElement.setAttribute("value", rcu.expression);
		utilityElement.appendChild(functionElement);
		
		
		//utilitiesElement.appendChild(utilityElement);
		
		if(rcu.enumvalues.size()>0)
		{
			//utworzenie i wstawienie tagu <enums\> do <utility\>
			Element enumsElement = doc.createElement("enums");
			utilityElement.appendChild(enumsElement);
			
			for(int j = 0; j<rcu.enumvalues.size(); j++)
			{
				//utworzenie tagu <enum\>
				Element enumElenment = doc.createElement("enum");
				enumElenment.setTextContent(rcu.enumvalues.get(j).feature);
				enumElenment.setAttribute("svalue", rcu.enumvalues.get(j).svalue);
				enumElenment.setAttribute("ivalue", rcu.enumvalues.get(j).ivalue);
				
				//wstawienie tagu <enum\> do <enums\>
				enumsElement.appendChild(enumElenment);
				
			}
		}
		
		//logger.debug("Created new utility xml Element from utility info: " + rcu.type);
		return utilityElement;
	}
	
	public Element getIntentionTag(Document doc, intention intni, String tagName)
	{
		Element intentionElement = doc.createElement(tagName);
		intentionElement.setAttribute("type", intni.type);
		
		Element clientElement = doc.createElement("client");
		clientElement.setTextContent(intni.client);
		intentionElement.appendChild(clientElement);
		
		Element agentElement = doc.createElement("agent");
		agentElement.setTextContent(intni.agent);
		intentionElement.appendChild(agentElement);
		
		Element maxElement = doc.createElement("maxterm");
		maxElement.setTextContent(intni.maxterm);
		intentionElement.appendChild(maxElement);
		
		Element outElement = doc.createElement("out");
		intentionElement.appendChild(outElement);
		
		for(int i = 0; i<intni.rcvOut.size(); i++)
		{
			Element validationElement = getResourceValidationTag(doc, intni.rcvOut.get(i), "validation");
			outElement.appendChild(validationElement);
		}
		
		//logger.debug("Created new intention xml Element from intention info: " + intni.type);
		return intentionElement;
	}
	
	public Element getServiceTag(Document doc, service srv, String tagName)
	{
		Element serviceElement = doc.createElement(tagName);
		serviceElement.setAttribute("type", srv.type);
		
		Element offertElement = doc.createElement("offert");
		offertElement.setTextContent(srv.offerValidity);
		serviceElement.appendChild(offertElement);
		
		Element realizetElement = doc.createElement("realizet");
		realizetElement.setTextContent(srv.realizeTerm);
		serviceElement.appendChild(realizetElement);
		
		Element intermsElement = doc.createElement("interms");
		serviceElement.appendChild(intermsElement);
		
		for(int i = 0; i<srv.resourcesTerm.size(); i++)
		{
			Element intermElement = doc.createElement("interm");
			intermElement.setTextContent(srv.resourcesTerm.get(i));
			intermsElement.appendChild(intermElement);
		}
		
		Element inElement = doc.createElement("in");
		Element outElement = doc.createElement("out");
		serviceElement.appendChild(inElement);
		serviceElement.appendChild(outElement);
		
		for(int i = 0; i<srv.rcvIn.size(); i++)
		{
			Element validationElement = getResourceValidationTag(doc, srv.rcvIn.get(i), "validation");
			inElement.appendChild(validationElement);
		}
		
		for(int i = 0; i<srv.rcOut.size(); i++)
		{
			Element resourceElement = getResourceTag(doc, srv.rcOut.get(i), "resource");
			outElement.appendChild(resourceElement);
		}
		
		//logger.debug("Created new service xml Element from service info: " + srv.type);
		return serviceElement;
	}
	
	public Element getOfferTag(Document doc, offer ofr, String tagName)
	{
		Element offerElement = doc.createElement(tagName);
		
		Element uuid = doc.createElement("uuid");
		Element ovdate = doc.createElement("cdate");
		Element client = doc.createElement("client");
		Element server = doc.createElement("server");
		Element agent = doc.createElement("agent");
		
		uuid.setTextContent(ofr.uuid);
		ovdate.setTextContent(ofr.cdate);
		client.setTextContent(ofr.client);
		server.setTextContent(ofr.server);
		agent.setTextContent(ofr.agent);
		
		offerElement.appendChild(uuid);
		offerElement.appendChild(ovdate);
		offerElement.appendChild(client);
		offerElement.appendChild(server);
		offerElement.appendChild(agent);
		
		Element serviceElement = getServiceTag(doc, ofr, "service");
		offerElement.appendChild(serviceElement);
		
		//logger.debug("Created new offer xml Element from offer info: " + ofr.type);
		return offerElement;
	}
	
	public Element getCounterOfferTag(Document doc, counteroffer cofr, String tagName)
	{
		Element coffer = doc.createElement(tagName);
		
		Element offeruuid = doc.createElement("offeruuid");
		offeruuid.setTextContent(cofr.offeruuid);
		coffer.appendChild(offeruuid);
		
		Element intention = getIntentionTag(doc, cofr, "rcout");
		coffer.appendChild(intention);
		
		Element rcin = doc.createElement("rcin");
		coffer.appendChild(rcin);
		
		//Element rcadvance = doc.createElement("rcadvance");
		//Element rcstuff = doc.createElement("rcstuff");
		//Element rcpay = doc.createElement("rcpay");
		
		if(cofr.rcsadvance.size()>0)
		{
			Element rcadvance = doc.createElement("rcadvance");
			rcin.appendChild(rcadvance);
			
			for(int i = 0; i<cofr.rcsadvance.size(); i++)
			{
				Element resourceset = doc.createElement("resourceset");
				
				Element type = doc.createElement("type");
				type.setTextContent(cofr.rcsadvance.get(i).type);
				resourceset.appendChild(type);
				
				if(cofr.rcsadvance.get(i).rc != null)
				{
					Element resource = getResourceTag(doc, cofr.rcsadvance.get(i).rc, "resource");
					resourceset.appendChild(resource);
				}			
				rcadvance.appendChild(resourceset);
			}
			
		}
		
		if(cofr.rcsstuff.size()>0)
		{
			Element rcstuff = doc.createElement("rcstuff");
			rcin.appendChild(rcstuff);
			
			for(int i = 0; i<cofr.rcsstuff.size(); i++)
			{
				Element resourceset = doc.createElement("resourceset");
				
				Element type = doc.createElement("type");
				type.setTextContent(cofr.rcsstuff.get(i).type);
				resourceset.appendChild(type);
				
				Element term = doc.createElement("term");
				term.setTextContent(cofr.rcsstuff.get(i).term);
				resourceset.appendChild(term);
				
				if(cofr.rcsstuff.get(i).rc != null)
				{
					Element resource = getResourceTag(doc, cofr.rcsstuff.get(i).rc, "resource");
					resourceset.appendChild(resource);
				}
				rcstuff.appendChild(resourceset);
			}
		}
		
		if(cofr.rcspay.size()>0)
		{
			Element rcpay = doc.createElement("rcpay");
			rcin.appendChild(rcpay);
			
			for(int i = 0; i<cofr.rcspay.size(); i++)
			{
				Element resourceset = doc.createElement("resourceset");
				
				Element type = doc.createElement("type");
				type.setTextContent(cofr.rcspay.get(i).type);
				resourceset.appendChild(type);
				
				if(cofr.rcspay.get(i).rc != null)
				{
					Element resource = getResourceTag(doc, cofr.rcspay.get(i).rc, "resource");
					resourceset.appendChild(resource);
				}
				rcpay.appendChild(resourceset);
			}			
		}
		
		//logger.debug("Created new counteroffer xml Element from counteroffer info: " + cofr.type);
		return coffer;
	}
	
	public Element getContractTag(Document doc, contract cntr, String tagName)
	{
		Element contractElement = doc.createElement(tagName);
		contractElement.setAttribute("uuid", cntr.uuid);
		contractElement.setAttribute("type", cntr.type);
		contractElement.setAttribute("state", cntr.state);
		
		Element clientElement = doc.createElement("client");
		clientElement.setTextContent(cntr.client);
		contractElement.appendChild(clientElement);
		
		Element agentElement = doc.createElement("agent");
		agentElement.setTextContent(cntr.agent);
		contractElement.appendChild(agentElement);
		
		Element serverElement = doc.createElement("server");
		serverElement.setTextContent(cntr.server);
		contractElement.appendChild(serverElement);
		
		return contractElement;
	}
	
	public Element getExtraTag(Document doc, extra ext, String tagName)
	{
		Element extra = doc.createElement(tagName);
		extra.setAttribute("name", ext.name);
		extra.setAttribute("value", ext.value);
		
		//logger.debug("Created new extra xml Element from extra info: " + ext.name + " " + ext.value);
		return extra;
	}
	
	//-----------------------------------------------------------------------------------------------------------------
	
	public resource getResourceInfo(Element resourceElement)
	{
		resource rc = new resource();
		//Element resourceElement = (Element) resourceItems.item(i);
		rc.type = resourceElement.getAttribute("type");
		
		NodeList resourceidList = resourceElement.getElementsByTagName("resourceid");
		NodeList ownerList = resourceElement.getElementsByTagName("owner");
		NodeList vdateList = resourceElement.getElementsByTagName("vdate");
		NodeList featuresList = resourceElement.getElementsByTagName("features");
		
		if(resourceidList.getLength()==1)
		{
			Element resourceidElement = (Element) resourceidList.item(0);
			rc.resourceid = resourceidElement.getTextContent();
		}
		
		if(ownerList.getLength()==1)
		{
			Element ownerElement = (Element) ownerList.item(0);
			rc.owner = ownerElement.getTextContent();
		}
		
		if(vdateList.getLength()==1)
		{
			Element vdateElement = (Element) vdateList.item(0);
			rc.vdate = vdateElement.getTextContent();
		}
		
		if(featuresList.getLength()==1)
		{
			Element featuresElement = (Element) featuresList.item(0);
			NodeList featureList = featuresElement.getElementsByTagName("feature");
			
			if(featureList.getLength()>0)
			{
				for(int j=0; j<featureList.getLength(); j++)
				{ 
					Element featureElement = (Element) featureList.item(j);
					feature ft = new feature(featureElement.getTextContent(), featureElement.getAttribute("value"));
					
					rc.features.add(ft);
				}
			}
			
		}
		
		//logger.debug("Created new resource info from resource xml Element: " + rc.type);
		return rc;
	}
	
	public utility getUtilityInfo(Element utilityElement)
	{
		utility ut = new utility();
		
		ut.type = utilityElement.getAttribute("type");
		
		NodeList function = utilityElement.getElementsByTagName("function");
		Element functionElement = (Element) function.item(0);
		ut.expression = functionElement.getAttribute("value");
		
		NodeList enums = utilityElement.getElementsByTagName("enums");
		if(enums.getLength()==1)
		{
			Element enumsElement = (Element) enums.item(0);
			NodeList enumsList = enumsElement.getElementsByTagName("enum");
			
			for(int j = 0; j<enumsList.getLength(); j++)
			{
				enumvalue ev = new enumvalue();
				
				Element enumElement = (Element) enumsList.item(j);
				ev.feature = enumElement.getTextContent();
				ev.svalue = enumElement.getAttribute("svalue");
				ev.ivalue = enumElement.getAttribute("ivalue");
				
				ut.enumvalues.add(ev);
			}
		}
		
		//logger.debug("Created new utility info from utility xml Element: " + ut.type);
		return ut;
	}
	
	public validation getValidationInfo(Element validationElement)
	{
		validation va = new validation();
		va.type = validationElement.getTextContent();
		va.condition = validationElement.getAttribute("value");
		va.intvalue = validationElement.getAttribute("intvalue");
		
		//logger.debug("Created new validation info from validation xml Element: " + va.type);
		return va;
	}
	
	public service getServiceInfo(Element serviceElement)
	{
		offer srv = new offer();
		
		srv.type = serviceElement.getAttribute("type");
		
		NodeList offert = serviceElement.getElementsByTagName("offert");
		NodeList realizet = serviceElement.getElementsByTagName("realizet");
		NodeList interms = serviceElement.getElementsByTagName("interms");
		
		NodeList in = serviceElement.getElementsByTagName("in");
		NodeList out = serviceElement.getElementsByTagName("out");
		
		if(offert.getLength() == 1)
		{
			Element offertElement = (Element) offert.item(0);
			srv.offerValidity = offertElement.getTextContent();
		}
		
		if(realizet.getLength() == 1)
		{
			Element realizetElement = (Element) realizet.item(0);
			srv.realizeTerm = realizetElement.getTextContent();
		}
		
		if(interms.getLength() == 1)
		{
			Element intermsElement = (Element) interms.item(0);
			NodeList interm = intermsElement.getElementsByTagName("interm");
			
			for(int i = 0; i<interm.getLength(); i++)
			{
				Element intermElement = (Element) interm.item(i);
				srv.resourcesTerm.add(intermElement.getTextContent());
			}
		}
		
		if(in.getLength() == 1)
		{
			Element inElement = (Element) in.item(0);
			NodeList rcv = inElement.getElementsByTagName("validation");
			
			for(int i = 0; i<rcv.getLength(); i++)
			{
				validation rcvi = getValidationInfo((Element) rcv.item(i));
				srv.rcvIn.add(rcvi);
			}
		}
		
		if(out.getLength() == 1)
		{
			Element outElement = (Element) out.item(0);
			NodeList rc = outElement.getElementsByTagName("resource");
			
			for(int i = 0; i<rc.getLength(); i++)
			{
				resource rci = getResourceInfo((Element) rc.item(i));
				srv.rcOut.add(rci);
			}
		}
		
		//NodeList in = serviceElement.getElementsByTagName("in");
		//NodeList out = serviceElement.getElementsByTagName("out");
		//logger.debug("Created new service info from service xml Element: " + srv.type);
		return srv;
	}
	
	public intention getIntentionInfo(Element intentionElement)
	{
		counteroffer intni = new counteroffer();
		
		intni.type = intentionElement.getAttribute("type");
		
		NodeList client = intentionElement.getElementsByTagName("client");
		NodeList agent = intentionElement.getElementsByTagName("agent");
		NodeList maxterm = intentionElement.getElementsByTagName("maxterm");
		NodeList out = intentionElement.getElementsByTagName("out");
		
		if(client.getLength() == 1)
		{
			Element clientElement = (Element) client.item(0);
			intni.client = clientElement.getTextContent();
		}
		
		if(agent.getLength() == 1)
		{
			Element agentElement = (Element) agent.item(0);
			intni.agent = agentElement.getTextContent();
		}
		
		if(maxterm.getLength() == 1)
		{
			Element maxtermElement = (Element) maxterm.item(0);
			intni.maxterm = maxtermElement.getTextContent();
		}
		
		if(out.getLength() == 1)
		{
			Element outElement = (Element) out.item(0);
			NodeList rcv = outElement.getElementsByTagName("validation");
			
			for(int i = 0; i<rcv.getLength(); i++)
			{
				validation rcvi = getValidationInfo((Element) rcv.item(i));
				intni.rcvOut.add(rcvi);
			}
		}
		
		//logger.debug("Created new intention info from intention xml Element: " + intni.type);
		return intni;
	}
	
	public offer getOfferInfo(Element offerElement)
	{	
		NodeList uuid = offerElement.getElementsByTagName("uuid");
		NodeList ovdate = offerElement.getElementsByTagName("cdate");
		NodeList client = offerElement.getElementsByTagName("client");
		NodeList server = offerElement.getElementsByTagName("server");
		NodeList agent = offerElement.getElementsByTagName("agent");
		NodeList offerList = offerElement.getElementsByTagName("service");
		
		Element servicElement = (Element) offerList.item(0);		
		offer ofr = (offer) getServiceInfo(servicElement);
		
		if(uuid.getLength() == 1)
		{
			Element uuidElement = (Element) uuid.item(0);
			ofr.uuid = uuidElement.getTextContent();
		}
		
		//logger.info("-------------> " + vdate.getLength());
		if(ovdate.getLength() == 1)
		{
			Element vdateElement = (Element) ovdate.item(0);
			ofr.cdate = vdateElement.getTextContent();
			//logger.info("-------------> " + ofr.vdate);
		}
		
		if(client.getLength() == 1)
		{
			Element clientElement = (Element) client.item(0);
			ofr.client = clientElement.getTextContent();
		}
		
		if(server.getLength() == 1)
		{
			Element serverElement = (Element) server.item(0);
			ofr.server = serverElement.getTextContent();
		}
		
		if(agent.getLength() == 1)
		{
			Element agentElement = (Element) agent.item(0);
			ofr.agent = agentElement.getTextContent();
		}
		
		
		//logger.debug("Created new offer info from offer xml Element: " + ofr.type);
		return ofr;
	}
	
	public counteroffer getCounterOfferInfo(Element counterOfferElement)
	{
		NodeList offeruuid = counterOfferElement.getElementsByTagName("offeruuid");
		NodeList rcout = counterOfferElement.getElementsByTagName("rcout");
		NodeList rcin = counterOfferElement.getElementsByTagName("rcin");
		String offerUUID = "";
		counteroffer coffer = null;
		
		if(offeruuid.getLength()>0)
		{
			Element uuidElement = (Element) offeruuid.item(0);
			offerUUID = uuidElement.getTextContent();
		}
		
		if(rcout.getLength()==0)
		{
			return coffer;
		}
		
		Element intentionElement = (Element) rcout.item(0);
		coffer = (counteroffer) getIntentionInfo(intentionElement);
		
		coffer.offeruuid = offerUUID;
		
		if(rcin.getLength()==1)
		{
			Element rcinElement = (Element) rcin.item(0);
			
			NodeList rcadvance = rcinElement.getElementsByTagName("rcadvance");
			NodeList rcstuff = rcinElement.getElementsByTagName("rcstuff");
			NodeList rcpay = rcinElement.getElementsByTagName("rcpay");
			
			if(rcadvance.getLength() == 1)
			{
				Element rcadvanceElement = (Element) rcadvance.item(0);			
				NodeList resourceset = rcadvanceElement.getElementsByTagName("resourceset");
				
				for(int i = 0; i<resourceset.getLength(); i++)
				{
					resourceset rcset = new resourceset();
					
					Element resourcesetElement = (Element) resourceset.item(i);
					NodeList type = resourcesetElement.getElementsByTagName("type");
					NodeList resource = resourcesetElement.getElementsByTagName("resource");
					
					if(type.getLength()==1)
					{
						Element typeElement = (Element) type.item(0);
						rcset.type = typeElement.getTextContent();
					}
					
					if(resource.getLength()==1)
					{
						Element resourceElement = (Element) resource.item(0);
						resource rc = getResourceInfo(resourceElement);
						rcset.rc = rc;
					}
					
					coffer.rcsadvance.add(rcset);
				}
			}
			
			if(rcstuff.getLength() == 1)
			{
				Element rcstuffElement = (Element) rcstuff.item(0);
				NodeList resourceset = rcstuffElement.getElementsByTagName("resourceset");
				
				for(int i = 0; i<resourceset.getLength(); i++)
				{
					resourceset rcset = new resourceset();
					
					Element resourcesetElement = (Element) resourceset.item(i);
					NodeList type = resourcesetElement.getElementsByTagName("type");
					NodeList term = resourcesetElement.getElementsByTagName("term");
					NodeList resource = resourcesetElement.getElementsByTagName("resource");
					
					if(type.getLength()==1)
					{
						Element typeElement = (Element) type.item(0);
						rcset.type = typeElement.getTextContent();
					}
					
					if(term.getLength()==1)
					{
						Element termElement = (Element) term.item(0);
						rcset.term = termElement.getTextContent();
					}
					
					if(resource.getLength()==1)
					{
						Element resourceElement = (Element) resource.item(0);
						resource rc = getResourceInfo(resourceElement);
						rcset.rc = rc;
					}
					
					coffer.rcsstuff.add(rcset);
				}
			}
			
			if(rcpay.getLength() == 1)
			{
				Element rcpayElement = (Element) rcpay.item(0);
				NodeList resourceset = rcpayElement.getElementsByTagName("resourceset");
				
				for(int i = 0; i<resourceset.getLength(); i++)
				{
					resourceset rcset = new resourceset();
					
					Element resourcesetElement = (Element) resourceset.item(i);
					NodeList type = resourcesetElement.getElementsByTagName("type");
					NodeList resource = resourcesetElement.getElementsByTagName("resource");
					
					if(type.getLength()==1)
					{
						Element typeElement = (Element) type.item(0);
						rcset.type = typeElement.getTextContent();
					}
					
					if(resource.getLength()==1)
					{
						Element resourceElement = (Element) resource.item(0);
						resource rc = getResourceInfo(resourceElement);
						rcset.rc = rc;
					}
					
					coffer.rcspay.add(rcset);
				}
			}
			
		}
		//logger.debug("Created new counteroffer info from counteroffer xml Element: " + coffer.type);
		return coffer;
	}
	
	public contract getContractInfo(Element contractElement)
	{
		contract cntri = new contract();
		
		cntri.uuid = contractElement.getAttribute("uuid");
		cntri.type = contractElement.getAttribute("type");
		cntri.state = contractElement.getAttribute("state");
		
		NodeList serverList = contractElement.getElementsByTagName("server");
		NodeList clientList = contractElement.getElementsByTagName("client");
		NodeList agentList = contractElement.getElementsByTagName("agent");
		
		if(serverList.getLength() > 0)
		{
			Element serverElement = (Element) serverList.item(0);
			cntri.server = serverElement.getTextContent();
		}
		
		if(clientList.getLength() > 0)
		{
			Element clientElement = (Element) clientList.item(0);
			cntri.client = clientElement.getTextContent();
		}
		
		if(agentList.getLength() > 0)
		{
			Element agentElement = (Element) agentList.item(0);
			cntri.agent =agentElement.getTextContent();
		}
		
		return cntri;
	}
	
	public extra getExtraInfo(Element extraElement)
	{
		extra ext = new extra();
		
		ext.name = extraElement.getAttribute("name");
		ext.value = extraElement.getAttribute("value");
		
		return ext;
	}

}
